═══ 1. Disclaimer ═══ This on-line document was generated automatically from its printed version LaTeX source. Some places in the document (especially tables) may look ugly due to the conversion program limits. These problems are being worked on and are supposed to be solved in the final release. ═══ 2. Title Page ═══ xTech Development System H2D User's Guide xTech Ltd, 1996 XDS software and documentation copyright (c) 1991-1996 xTech Ltd. (xTech). Information in this document is subject to change without notice and does not represent a commitment on the part of xTech. All rights reserved. You may use the enclosed software on a single computer; transfer the software from one computer to another, provided that the software is used on only one computer at a time and that you remove any copies of the software on the computer from which the copies were made; make copies of the software for backup purposes only. XDS software and documentation have been tested and reviewed. Nevertheless, xTech makes no warranty or representation, either express or implied, with respect to the software and documentation included with XDS. In no event will xTech be liable for direct, indirect, special, incidental or consequential damages resulting from any defect in the software or documentation included with this product. In particular, xTech shall have no liability for any programs or data used with this product, including the cost of recovering programs or data. XDS is a trademark of xTech Ltd. All trademarks and copyrights mentioned in this documentation are the property of their respective holders. ═══ 3. Introduction ═══  About H2D  Typographic conventions ═══ 3.1. About H2D ═══ Sooner or later, every Modula-2 programmer encounters four problems. These are: absence, incompleteness, unportability, and low quality of libraries. At the same time, C/C++ programmers usually have problems choosing from a huge set of free, public domain, shareware, and commercial libraries of various purpose, size, and quality which are in many cases portable or are available for a number of platforms. Moreover, the Application Programming Interfaces (APIs) of the most widely used software products (operating systems, database engines, etc.), are defined in terms of the C programming language. In order to use all this stuff from Modula-2, a programmer needs, first, a Modula-2 compiler which supports C calling/naming conventions and a set of types corresponding to C types, and, second, definition modules corresponding to the C headers of the library/API. Finding a suitable compiler is not a very big deal, but manual conversion of C headers turns to a real nightmare when it comes to, say, the X Window API. That is why we created H2D. H2D does the job automatically, i.e. translates C header files into Modula-2 definition modules. H2D is intended to be used with XDS version 2.10 or later and is included in the XDS distribution package. However, the generated definition modules may be used with any ISO-compliant Modula-2 compiler. The required modifications are minor and may be done using text editor macros or a simple REXX, sed, etc script. The source language is a subset of ANSI C, which includes declarations and preprocessor directives, with some extensions (See Non-standard qualifiers and Chapter Non-standard preprocessor directives). Destination language is ISO Modula-2 with XDS language extensions, but in XDS resulting definition modules may be used with both Modula-2 and Oberon-2. H2D generates definition modules suitable for either XDS-C, Native XDS, or both. In case of Native XDS, module template for function-like C macros may be generated (See Native code). In case of XDS-C, an extra header file containing C declarations of types introduced by H2D is generated (See Convertor to C). ═══ 3.2. Typographic conventions ═══  Language descriptions  Source code fragments ═══ 3.2.1. Language descriptions ═══ Where formal descriptions for language syntax constructions appear, an extended Backus-Naur Formalism (EBNF) is used. These descriptions are set in the Courier font. Text = Text [{Text}] | Text. In EBNF, brackets [ and ] denote optionality of the enclosed expression, braces { and } denote repetition (possibly 0 times), and the line | denotes other possible valid descriptions. Non-terminal symbols start with an upper case letter (e.g. Statement). Terminal symbols either start with a lower case letter (e.g. ident), or are written in all upper case letters (e.g. BEGIN), or are enclosed within quotation marks (e.g. ":="). ═══ 3.2.2. Source code fragments ═══ When fragments of a source code are used for examples or appear within a text they are set in the Courier font. /* example.h */ typedef unsigned long int UINT; ═══ 4. Configuring H2D ═══  System search path  Working configuration  Directory hierarchies  Redirection file  Configuration file  Customizing H2D messages ═══ 4.1. System search path ═══ In order that your operating system should know where to find the executable binary files which constitute the H2D package, you have to setup your operating system search path properly. Refer to the readme.1st file from the on-line documentation. ═══ 4.2. Working configuration ═══ The H2D working configuration includes an executable file and a set of system files: ─────────────────────────────────────────────────────────────────────────── h2d.red Search path redirection file (See Redirection file) h2d.cfg Configuration file (See Configuration file) h2d.msg Contains texts of error messages (See Customizing H2D messages) ─────────────────────────────────────────────────────────────────────────── Upon invocation, H2D tries to locate the h2d.red file in the current directory. If h2d.red is found, all other files are searched for/created using paths defined in h2d.red, otherwise they are considered to reside in the current directory. The configuration file contains various H2D settings. If the configuration file is not found, default settings are used. ═══ 4.3. Directory hierarchies ═══ H2D gives you complete freedom over where you keep your header files and any files which H2D itself creates for further use. It is advisable to work in a project oriented fashion - i.e. to have a separate directory hierarchy for each individual project. Each project should have a main working directory. The script called h2duser can be used to create all required subdirectories and system files (e.g. h2d.red). For example, to create a directory structure for a project called myproj, issue the following commands: md myproj cd myproj h2duser H2D keeps the directory hierarchies of original header files. Usually the directory containing header files has some subdirectories. All H2D output directories must contain the same subdirectories. ??? ═══ 4.4. Redirection file ═══ Upon activation, H2D looks for a file called h2d.red - the redirection file. This file defines directories in which all other files are searched for. The redirection file has to be placed in the current directory. A redirection file consists of several lines of the form: Pattern = directory {";" directory} Pattern is a regular expression which all file names used by H2D will be compared with. A regular expression is a string containing certain special characters: ─────────────────────────────────────────────────────────────────────────── Sequence Denotes * an arbitrary sequence of any characters, possibly empty (equivalent to {\000-\377} expression) ? any single character (equivalent to [\000-\377] expression) [...] one of the listed characters {...} an arbitrary sequence of the listed characters, possibly empty \nnn the ASCII character with octal code nnn, where n is [0-7] & the logical operation AND | the logical operation OR ^ the logical operation NOT (...) the priority of operations ─────────────────────────────────────────────────────────────────────────── A sequence of the form a-b used within either [] or {} brackets denotes all characters from a to b. When H2D looks for or intends to create a file, its name is sequentially compared with all patterns from the top of the redirection file. The file is created in the first directory of the list corresponding to the matched pattern. The file is searched for in all directories in the list (from first to last) until it is found or the directory list is exhausted. If a match is not found, the file is created or searched for in the current directory. Note: If a match is found, the current direcory is not searched unless it is explicitly specified in the directory list. It is possible to put comment lines into the redirection file. A comment line should be started with the % character.  Example ═══ 4.4.1. Example ═══ *.h = h; .; c:\bc\include mac_*.def = macro; *.def = def; mac_*.mod = macro; *.h2d = h2d; h2d.cfg = .; cfg; c:\h2d; h2d.msg = .; cfg; c:\h2d; ═══ 4.5. Configuration file ═══ The configuration file is used to set options which control various aspects of H2D behaviour: names of generated files, source/target language extensions, mapping of C types to Modula-2 etc. An option is a pair (name, value). Every line in the configuration file may contain only one option setup directive. Arbitrary spaces are permitted. The "//" characters mark the comment line; a line started with it is discarded. Setup directives have the following syntax: Setup_directive = name "="" value "";" Options, their meanings and valid values are described in Chapter Options Reference.  Example ═══ 4.5.1. Example ═══ % This is a comment line % EXTENSION OF OUTPUT FILES: OutputExtension = def % TYPE OF OUTPUT DEFINITION FILE % POSSIBLE VALUES: C_Code, Native, Common BackEnd = Common % GENERATE DEFINITION AND IMPLEMENTATION MODULES FOR MACROS GenerateMacrosFile = On % PREFIX FOR GENERATED DEFINITION FILES DefinitionFilePrefix = h2d_ % PREFIX FOR GENERIC MACRO MODULES MacrosFilePrefix = mac_ % MAXIMUM STRING LENGTH IN OUTPUT FILE: MaxStrLen = 70 % COMMENT POSITION CommentPosition = 40 % FIRST PARSED HEADER: PreHeader = borlandc.h % PACKET FILE NAME: PacketFile = borlandc.h2d % RETRANSLATE FLAG: Retranslate = Off % PROGRESS FLAG: Progress = On % C STANDARD LIBRARY FLAG: CStdLib = On % C++ COMMENTS FLAG: CPPComment = On % MERGING ALL HEADERS TO ONE HeadersMerging = Off % ADD PATH TO MODULE AND FILE NAME LongFileName = On % Set or Reset XDS option M2UNPACKTYPES M2UnpackTypes = On % INSERTING HEAD BEFORE EACH MERGED HEADER HeadInserting = On % C BASE TYPES SYNONYMS: signed_char = CHAR signed_int = SYSTEM.int signed_short_int = SYSTEM.INT16 signed_long_int = LONGINT unsigned_char = SHORTCARD unsigned_int = SYSTEM.unsigned unsigned_short_int = SYSTEM.CARD16 unsigned_long_int = LONGCARD float = REAL double = LONGREAL long_float = UNDEF long_double = UNDEF void = SYSTEM.void ═══ 4.6. Customizing H2D messages ═══ The file h2d.msg contains error messages in the form number Text The following is an extract from h2d.msg: 001 Can't open file %s ... 010 Invalid use of modifier ... Some messages contain format specifiers for additional arguments. In the example above, the message number 001 contains the %s specifier which is substituted with a file name when a message is printed. In order to use the language other than English for messages it is necessary to translate the text of the messages, preserving error numbers and the number and order of format specifiers. ═══ 5. Getting Started ═══ In this chapter we assume that H2D is properly installed and configured (See Chapter Configuring H2D). Your H2D package contains a script file to create the working environment. It is called h2duser. For more information consult the readme.1st file from your on-line documentation.  Invoking H2D  H2D usage example  Error reporting  Using generated definition modules ═══ 5.1. Invoking H2D ═══ H2D is implemented as a command line utility. To invoke it, type h2d { header_file } at the command prompt, where header_file is a header file name. H2D translates all files specified on the command line. To invoke H2D with a project filename, type h2d =p project_file If invoked without parameters, the h2d utility prints its help information. ═══ 5.2. H2D usage example ═══ In the working directory, use your favourite text editor to create a file named example.h: /* example.h */ #define FALSE 0 #define TRUE 1 #define equal 10 #define more 20 #define less 30 typedef int BOOL; typedef int INTEGER; struct tree{ INTEGER key; /* key */ struct tree *right; /* right subtree */ struct tree *left; /* left subtree */ }; #define compare(arg1, arg2) ((arg1.key == arg2.key)?(equal):\ ((arg1.key>arg2.key)?(more):(less))) void insert(struct tree *head, INTEGER key); BOOL find(struct tree *head, INTEGER key); Create a file h2d.cfg which contains the following lines: OutputExtension = def BackEnd = Common GenerateMacrosFile = On DefinitionFilePrefix = h2d_ MacrosFilePrefix = mac_ Now, type h2d example.h at the command prompt. The H2D banner line will appear: H2D v1.00 (c) xTech 1995 File example.h Assuming that you have typed the source file correctly, after translation, the translator will display: no errors, lines 24. ---------------------------------------------- Files 1, lines 24, no errors, time 0:2. showing the number of errors, the number of source lines in the file, and some statistics. The following files will be generated: ───────────────────────────────────────────────────────── h2d_example.def basic definition module h2d_example.h definitions of types generated by H2D mac_example.def generic macro definition module mac_example.mod generic macro implementation module ───────────────────────────────────────────────────────── (* h2d_example.def Apr 14 17:29:7 1996 *) (* Generated by H2D v1.00 from example.h. *) <*+ M2ADDTYPES *> <*+ M2EXTENSIONS *> <*+ M2UNPACKTYPES *> <*+ NOHEADER *> <*# IF NOT DEFINED(GENCTYPES) THEN *> <* NEW GENTYPEDEF+ *> <*# END *> <*+ CSTDLIB *> DEFINITION MODULE ["C"] h2d_example; IMPORT SYSTEM; (* H2D: to import this module write following text: IMPORT h2d_example; *) CONST FALSE = 0; TRUE = 1; equal = 10; more = 20; less = 30; TYPE BOOL = SYSTEM.int; INTEGER = SYSTEM.int; <*- GENTYPEDEF *> Ptrtree = POINTER TO tree; <*+ GENTYPEDEF *> tree = RECORD key : INTEGER; (* key *) right: Ptrtree; (* right subtree *) left : Ptrtree; (* left subtree *) END; <*# IF __GEN_C__ THEN *> (* H2D: this procedure was generated from Macro. *) PROCEDURE compare ( arg1, arg2: ARRAY OF SYSTEM.BYTE ); <*# ELSE *> PROCEDURE / compare * ( arg1, arg2: ARRAY OF SYSTEM.BYTE ); <*# END *> PROCEDURE insert ( head: Ptrtree; key: INTEGER ); PROCEDURE find ( head: Ptrtree; key: INTEGER ): BOOL; END h2d_example. /* h2d_example.h Apr 14 17:29:7 1996 */ /* Generated by H2D v1.00 from module h2d_example and h-file example.h. */ /* This file contains types was created during translation */ #include typedef struct tree * Ptrtree; (* mac_example.def Apr 14 17:29:7 1996 *) (* Generated by H2D v1.00 from example.h. *) <*+ M2ADDTYPES *> <*+ M2EXTENSIONS *> <*+ M2UNPACKTYPES *> (* This module needs for macros realise *) DEFINITION MODULE mac_example; IMPORT SYSTEM; PROCEDURE ["C"] compare ( arg1, arg2: ARRAY OF SYSTEM.BYTE ); END mac_example. (* mac_example.mod Apr 14 17:29:7 1996 *) (* Generated by H2D v1.00 from example.h. *) <*+ M2ADDTYPES *> <*+ M2EXTENSIONS *> <*+ M2UNPACKTYPES *> (* This module needs for macros realise *) IMPLEMENTATION MODULE mac_example; IMPORT SYSTEM; PROCEDURE ["C"] compare ( arg1, arg2: ARRAY OF SYSTEM.BYTE ); (* #define compare(arg1, arg2) ((arg1.key == arg2.key)?(equal):\ ((arg1.key>arg2.key)?(more):(less))) *) BEGIN END compare; END mac_example. ═══ 5.3. Error reporting ═══ When H2D detects an error in the input file, it displays an error report. It contains the file name and position (line and column numbers) where the error occurred: Error [ example.h 16:44 ] ** Duplicate identifier 'insert', The error which is often encountered is Error [...] ** Expected , or ; In most cases it means that some identifier is undefined for some reason. Try to put "," or ";" at the specified position to find out what is the problem source. ═══ 5.4. Using generated definition modules ═══ H2D generates one or more Modula-2 definition modules for each header file. Each definition module has a comment after the import section similar to the follofing: (* H2D: to import this module write following text: IMPORT a, m1; *) In order to use this definition module, you have to add the commented IMPORT clause to the import section of your module. If some of the modules listed in it are already imported, you may wish to remove duplicated names. ═══ 6. Translation Rules ═══  Comments  Identifiers  Types  Type synonyms  Variables  Function prototypes  Non-standard qualifiers  Preprocessor directives  Module names ═══ 6.1. Comments ═══ All comments from original C text are copied to generated definition modules. Their placement, however, is not preserved in some cases. The CommentPosition option may be used to align comments which are placed next to declarations. C++ compilers are usually able to recognize C++-style comments (beginning with '//') even while operating in C mode. The CPPComment option controls whether H2D recognizes these comments as well. ═══ 6.2. Identifiers ═══ In most cases, H2D preserves original C identifiers. Exceptions are structure, union, and enumeration tags, which constitute a separate name space in C. If there is a constant, type, variable, or function identifier which coincides with a tag, H2D appends "_struct", "_union" or "_enum" to that tag. In some circumstances, H2D itself generates additional identifiers, e.g. for unnamed function arguments (see Function prototypes), formal types (see Function prototypes), and recursively defined pointer types of structure fields (see Types). H2D may append digits to generated identifiers to avoid conflicts with existent ones. Identifiers matching Modula-2 keywords are not allowed in source files.  Example ═══ 6.2.1. Example ═══ The following C declarations were taken from the sys/stat.h file: struct stat { ... }; int stat( const char *, struct stat * ); TYPE stat_struct = RECORD ... END; PtrChar = POINTER TO CHAR; PROCEDURE stat(arg0: PtrChar; arg1: stat_struct): SYSTEM.int; ═══ 6.3. Types ═══ C types are translated to Modula-2 types according to the following table: ────────────────────────────────────────────────── C type Modula-2 type base (int, char, etc) see C base types mapping void* SYSTEM.ADDRESS pointer pointer array array enumeration enumeration structure record union variant record pointer to function procedure type ────────────────────────────────────────────────── Notes:  The C enumeration (enum) is not actually a distinct type - it is just a convenient way to declare integer constants (but in C++ enumeration is a distinct type). However, H2D translates it into the Modula-2 enumeration type, unless it enumeration contains constants with explicitly specified values. In the latter case, Modula-2 constant declaration is generated.  Structure, union, and enumeration tags are not preserved in cases of collision. It may cause problems with Modula-2 to C convertors (e.g. XDS-C). See Identifiers.  A C structure may contain fields which type is defined as pointer to that structure. In this case H2D automatically declares necessary pointer type: struct Node { TYPE int i; PtrNode = POINTER TO Node; struct Node *next; Node = RECORD }; i: SYSTEM.int; next: PtrNode; END;  Examples ═══ 6.3.1. Examples ═══ struct STRUCTURE{ TYPE STRUCTURE = RECORD int field1; field1: SYSTEM.int; char field2; field2: CHAR; double field3; field3: LONGREAL; }; END; union UNION { TYPE UNION = RECORD int field1; CASE : INTEGER OF char field2; 0: field1: SYSTEM.int; double field3; |1: field2: CHAR; }; |2: field3: LONGREAL; END; END; ═══ 6.4. Type synonyms ═══ C declarations of type synonyms (typedef) are translated to Modula-2 type declarations. If there are multiple synonyms declared for a type, their equivalence is preserved: typedef char String[256]; TYPE String = ARRAY [0..255] OF CHAR; typedef String *PString; PString = POINTER TO String; typedef String *Buffer; Buffer = PString; Note: Function type synonyms may be used in function declarations. These synonyms are not translated; functions are translated as usual (see Function prototypes). ═══ 6.5. Variables ═══ Variables are translated to variables. Variables declared with the const qualifier are translated to read-only variables (XDS extension). The volatile qualifier is ignored. extern int i; VAR i : SYSTEM.int; extern const int j; VAR j- : SYSTEM.int; ═══ 6.6. Function prototypes ═══ C function prototypes declared as void are translated to proper procedure declarations; other are translated to function procedure declarations. If there is no name specified for the function parameter, argx is substituted, where x is a number unique for each unnamed parameter. In C, a derived type (more precisely, pointer or array) may be specified for a function parameter. In Modula-2, the formal type of a procedure parameter have to be either type name or open array type. H2D translates parameters of array type to open array parameters. (??? VAR or not ???) The translation procedure for pointers is more complex. By default, H2D searches for a type synonym, previously declared via typedef. The synonym, if found, is used as formal type; otherwise H2D automatically declare one. If automatic declaration is undesirable, required synonyms may be declared in the project file. Other variants of translation may be explicitly specified by means of the #parameters directive. See also Non-standard qualifiers.  Examples ═══ 6.6.1. Examples ═══ void p(int,int); PROCEDURE p ( arg0 : SYSTEM.int; arg1 : SYSTEM.int ); int f(char c); PROCEDURE f ( c : CHAR ): SYSTEM.int; void P(T *t); TYPE PtrT = POINTER TO T; PROCEDURE P ( t : PtrT ); void Q(T t[]) PROCEDURE Q ( t : ARRAY OF T ); int strlen(char *); PROCEDURE strlen ( arg0 : ARRAY OF CHAR ) #parameters : SYSTEM.int; strlen(0) : ARRAY #end ═══ 6.7. Non-standard qualifiers ═══ In practice, header files are not "pure" ANSI C. The most common extension is a set of additional keywords (qualifiers) which may be used to specify calling/naming conventions used in a particular library or API. Since XDS provides the similar mechanism called direct language specification (DLS), H2D recognizes a number of such keywords, which are translated to the following DLS strings: ────────────────────────────────────────────── C keyword DLS String cdecl none fortran none !!! warning interrupt none !!! warning pascal "Pascal" for types and variables "StdCall" for functions ??? syscall "Syscall" ────────────────────────────────────────────── near, far, and huge qualifiers are recognized but ignored. ═══ 6.8. Preprocessor directives ═══  Macro definitions  Headers inclusion  Conditional compilation  Other directives ═══ 6.8.1. Macro definitions ═══ The #define C preprocessor directive may contain an object-like definition or a function-like definition which are translated differently. #define identifier Text If Text is a constant expression, the directive is translated to a constant declaration. If Text is a type identifier, the directive is translated to a type declaration. If Text is an identifier of a function, a macro definition, or a constant, the directive is translated to a constant declaration. In all other cases, it is interpreted in a C preprocessor manner. #define identifier"(" idenifier, { identifier } ")" Text Translated to a proper procedure declaration with all parameters having type ARRAY OF SYSTEM.BYTE. These declarations are marked with a special comment and may be corrected after translation to reflect the actual semantics of a macro by changing parameter types and/or adding return types. See also Native code #undef identifier Undefines identifier as it is done by a C preprocessor.  Example ═══ 6.8.1.1. Example ═══ #define constant 0x10 #define constant_synonym constant #define macro_with_params(p1, p2, p3) Text #define macro_with_params_synonym macro_with_params int function(int); #define function_synonym function typedef int INT; #define INTEGER INT is translated to CONST constant = 10H; constant_synonym = constant; <*# IF __GEN_C__ THEN *> (* H2D: this procedure was generated from Macro. *) PROCEDURE macro_with_params( p1, p2, p3: ARRAY OF SYSTEM.BYTE ); CONST macro_with_params_synonym = macro_with_params; <*# END *> PROCEDURE function ( arg0: SYSTEM.int ): SYSTEM.int; CONST function_synonym = function; TYPE INT = SYSTEM.int; INTEGER = INT; ═══ 6.8.2. Headers inclusion ═══ #include #include "file_name" If the file specified by file_name has to be merged with the current file (see Included headers), H2D treats this directive exactly as a C preprocessor, i.e. replaces it with contents of a specified file. Otherwise, file_name is added to the import list and the file specified by it is translated into a separate definition module. The LongFileName option controls conversion of included header file names which contain path: #include IMPORT stat; (* LongFileName is OFF *) IMPORT sys_stat; (* LongFileName is ON *) See also Module names ═══ 6.8.3. Conditional compilation ═══ H2D handles conditional compilation directives #if, #ifdef, #ifndef, #else, and #endif the same way as a C preprocessor does. A project filemay be used to define constants which are used in arguments of these directives. Most C compilers have a set of predefined macros H2D knows nothing about. These macros also may be defined in the pre-header file. ═══ 6.8.4. Other directives ═══ H2D recognizes and ignores #line, #error, and #pragma C preprocessor directives. ═══ 6.9. Module names ═══ By default, H2D uses a header file name without ".h" extension as a definition module name. If a file name contains characters which are not allowed in identifiers, the #name directive directive must be used to specify a proper identifier. ═══ 7. Using H2D ═══  Packet file  Included headers  Fitting Modula-2 compiler  Advanced features ═══ 7.1. Packet file ═══ ═══ 7.2. Included headers ═══ A C header file may contain one or more #include directives. H2D offer the following translation variants for included headers:  All headers are merged and translated into a single definition module (the HeadersMerging option is set ON).  Each included header is translated into a separate definition module which name is added to the import list (the HeadersMerging option is set OFF).  The headers which have to be merged are explicitly specified using the #merge directive (the HeadersMerging option must be OFF). The #merge directive provides more flexible method of merging control than the HeadersMerging option. The example illustrates situation in which this directive is very helpful. If the HeadInserting option is set ON, H2D separates pieces of Modula-2 text, which correspond to different merged headers, with comments containing header file names.  Example ═══ 7.2.1. Example ═══ /* m1.h */ /* m2.h */ typedef int INTEGER; struct descriptor{ #include INTEGER handl; #include }; #include typedef int far * RETVAL; RETVAL handler(); /* end m2.h */ /* end m1.h */ In this example, the RETVAL declaration from m2.h is used in m1.h. On the other hand, m2.h uses the declaration from m1.h (INTEGER). Setting the HeadersMerging option to On in the configuration file results in all headers (m1.h, m2.h, m3.h, and m4.h) being merged and translated into the single definition module m1. If this is not a desired behaviour, the #merge directive should be used instead. If the HeadersMerging option is OFF and the line #merge is added to either m1.h or the corresponding #module directive in a project file, H2D produces three definition modules m1, m3 and m4, where m1 is a result of translation of two merged headers m1.h and m2.h. ═══ 7.3. Fitting Modula-2 compiler ═══ Some of H2D translation rules depend on the target Modula-2 compiler; even XDS-C and Native XDS require different definition modules. The BackEnd option is used to reflect the major difference: whether the target Modula-2 compiler is implemented as a native code compiler (BackEnd = Native) or a convertor to C (BackEnd = C_Code). It is also possible to produce definition modules suitable for both XDS-C and Native XDS (BackEnd = Common). In this case H2D encloses target-dependent parts in XDS conditional compilation directives. Another parameter which has to be explicitly specified in most cases is a set of Modula-2 types corresponding to C base types, such as int.  Native code  Convertor to C  C base types mapping ═══ 7.3.1. Native code ═══ C headers often contain a number of useful function-like macros. These macros are translated into procedure declarations with parameters having type ARRAY OF SYSTEM.BYTE, which is assignment compatible with any other type. But C macros exist only at compile-time and are not present in object files. Therefore, a Modula-2 compiler is unable to handle them properly unless it is implemented as a convertor to C. Nevertheless, H2D provides a technique which allows to use C function-like macros even with a native code Modula-2 compiler. If the BackEnd option is set to either Native or Common and the GenerateMacroFile option is set ON, H2D generates, along with the main definition module, additional definition and implementation modules. Procedures corresponding to function-like macros, are declared as external in the main definition module. Actual declaration and template implementation (with no body, but comment with C macro definition) of these procedures are placed into additional definition and implementation modules respectively. The additional module name is constructed from the main definition module name and a prefix specified by the MacrosFilePrefix option.  Example ═══ 7.3.1.1. Example ═══ Have to write something here. ═══ 7.3.2. Convertor to C ═══ If the Modula-2 compiler is actually a convertor to C (e.g. XDS-C), it converts definition modules written by a programmer to C headers. But headers corresponding to definition modules generated by H2D already exist. To prevent them from being overridden, H2D inserts the NOHEADER XDS option, which disables header file generation, at the beginning of each definition module. For all included header files, H2D also sets the CSTDLIB XDS option according to the parenthesis used in the #include directive - double quotes or angle brackets. For top-level header files, this option is set equal to the value of the CStdLib option. H2D usually has to introduce a number of additional types in the definition module (see Function prototypes and Types). These types are absent in the original header file, and their usage would cause C compilation to fail. To solve this problem, H2D constructs a definition module name from a header file name and a prefix specified by the DefinitionFilePrefix option. Then, a "wrapper" header file is generated, which includes the original header file and contains required type declarations. Its name corresponds to the name of a definition module. Type declarations from a project fileare not copied to wrapper in the current release, but this will be implemented in the future. ═══ 7.3.3. C base types mapping ═══ The following options may be used in the configuration file to specify Modula-2 types corresponding to C base types: ───────────────────────────────────────────────────────────────────── Option Default value Option Default value signed_char ??? unsigned_char ??? signed_short_int ??? unsigned_short_int ??? signed_int ??? unsigned_int ??? signed_long_int ??? unsigned_long_int ??? float ??? double ??? long_float ??? long_double ??? ───────────────────────────────────────────────────────────────────── The M2UnpackTypes option sets value of the M2UNPACKTYPES XDS option, which affects representation of BOOLEAN, set and enumeration types. ═══ 7.4. Advanced features ═══  BITSET generation  Pointer type function parameters  Project file ═══ 7.4.1. BITSET generation ═══ The C programming language, as well as C++, has no built-in set type. The common practice is to treat unsigned integer types as bit scales and to use bitwise logical operators to manipulate them. Since Modula-2 provides set types (and no bitwise operators), it would be more convenient to translate individual integer constants and types to set constants and types. The #bitset directive is intended to explicitly specify C objects of type unsigned long int (and its synonyms) which has to be translated to objects of the Modula-2 BITSET type. It may happen that all unsigned long int objects in a particular header have to be translated to BITSET. For example, a header may contain only #define directives which define constants allowed as actual parameters of a certain set of library functions. In this case, a special form of the #bitset directive may be used, which forces all objects of type unsigned long int and all unsigned constants to be translated to the BITSET type objects. Note: In order to keep original headers intact, #bitset directives may be placed into the project file inside the corresponding #module directive. The #bitset directive can not be used in the pre-header file outside a #module directive.  Example ═══ 7.4.1.1. Example ═══ struct s{ unsigned long int field; }; typedef unsigned long int UINT; unsigned long int variable; unsigned long int function(unsigned long int argument); unsigned long int array[10]; #define constant 0x11u #bitset s.field; UINT; variable; function; function(0); array[]; constant; #end is translated to TYPE s = RECORD field: BITSET; END; UINT = BITSET; VAR variable: BITSET; PROCEDURE function ( argument: BITSET ): BITSET; VAR array: ARRAY [0..9] OF BITSET; CONST constant = {0, 4}; ═══ 7.4.2. Pointer type function parameters ═══ In C, the actual semantics of a pointer type function parameter depends on that function and cannot be determined automatically. A function may interpret its parameter of type T* as either:  pointer to T (type defined as POINTER TO T)  single value passed by reference (VAR T)  array (ARRAY OF T)  array passed by reference (VAR ARRAY OF T) where the corresponding Modula-2 formal types are given in parenthesis. The non-standard #parameters directive may be used to explicitly point out the semantics of each pointer type parameter. Note: In order to keep original headers intact, #parameters directives may be placed into the project fileinside the corresponding #module directive. The #parameters directive can not be used in the pre-header file outside a #module directive.  Example ═══ 7.4.2.1. Example ═══ #parameters function(0): VAR; function(1): ARRAY; function(2): VAR ARRAY; #end void function(int*, int*, int*, int*); is translated to: TYPE PtrSInt = POINTER TO SYSTEM.int; PROCEDURE function ( VAR arg0: SYSTEM.int; arg1: ARRAY OF SYSTEM.int; VAR arg2: ARRAY OF SYSTEM.int; arg3: PtrSInt ); ═══ 7.4.3. Project file ═══ The most powerful and multi-purpose feature of H2D is the project file, which name may be specified at the command line after =p. The project file may be used:  To set values of H2D options for a particular set of files  To map calling/naming convention qualifiers used by a particular C compiler to those supported by H2D (see Non-standard qualifiers), or to make them ignorable, e.g.: #module <*.h> /* define for all headers */ #define _System syscall #define far #end  To define macros which are predefined by the C compiler or are used in conditional compilation preprocessor directives (see Conditional compilation): #module <*.h> #define __WATCOM_C__ #define INCL_DOS #end  To declare type synonyms in order to prevent H2D from automatic type declarations (see Function prototypes and Types): #module <*.h> typedef char *String /* no more PtrChar */ #end  To collect all non-standard preprocessor directives in order to keep original header files intact (see Chapter Non-standard preprocessor directives): #module #parameters strlen(0) : ARRAY #end #end Finally, a list of header files which have to be translated may be specified in a project file using the ???: #header #header This technique has one more advantage. A header file name may occur multiple times in #include directives. H2D keeps information about each translated header in memory, and if an already transtaled header file is encountered, it is not processed again. Note: In this case H2D requires more memory.  Example ═══ 7.4.3.1. Example ═══ The header files a.h and m1.h /* a.h */ #include "m1.h" #define constant1 0x11u __PASCAL function3( float * arg0, unsigned long arg1 ); /* end a.h */ /* m1.h */ #define constant2 0x111u __PASCAL function1( float * arg0, float * arg1 ); function2( unsigned long arg0, unsigned long arg1 ); /* end m1.h */ with pre-header file h2d.h: #define __PASCAL pascal #module "a.h" #merge "m1.h" #end #module "m1.h" #parameters function1 (1): VAR; #end #bitset constant2; function2 (1); #end #end are translated to (* ************************ *) (* m1.h *) (* ************************ *) CONST constant2 = {0, 4, 8}; <*- GENTYPEDEF *> TYPE PtrFloat = POINTER TO REAL; PROCEDURE ["StdCall"] function1 ( arg0: PtrFloat; VAR arg1: REAL ): SYSTEM.int; PROCEDURE function2 ( arg0: LONGCARD; arg1: BITSET ): SYSTEM.int; (* *********************** *) (* a.h *) (* *********************** *) CONST constant1 = 111H; PROCEDURE ["StdCall"] function3 ( arg0: PtrFloat; arg1: LONGCARD ): SYSTEM.int; ═══ 8. Non-standard preprocessor directives ═══ H2D recognizes a number of non-standard preprocessor directives. These are #bitset, #merge, #module, #name, and #parameters. There are two important things about them:  All these directives are related to the definiton module generation only and do not affect the C text. Therefore, they may be placed arbitrarily in the source file, unlike the standard ones.  The scope of the #bitset, #merge, and #parameters directives is either the file where these directives are placed, of the file specified in the surrounding #module directive.  #bitset  #merge  #module  #name  #parameters ═══ 8.1. #bitset ═══ #bitset "unsigned;" | Designator ";" { Designator ";" } #end Designator = identifier { "^" | "[ ]" | "." identifier | "(" number ")" } "unsigned" means that unsigned long int is always translated to BITSET and all unsigned constants are translated to BITSET constants. If there is a designator list instead of "unsigned", then only objects listed in it are translated to corresponding BITSET objects. Designator specifies a named object and access operations for its element which has to be translated to BITSET: ─────────────────────────────────────────────────────────── "^" pointer dereference "[ ]" array indexing "." identifier structure or union field access "(" number ")" zero-based number of a function argument ─────────────────────────────────────────────────────────── The #bitset directive has effect only in the file where it is located, or in the file specified in the surrounding #module directive, Therefore, Designator should specify an object declared in this file. If there is no object specified by Designator or if its type is not unsigned long int, an error message is displayed. See also BITSET generation.  Example ═══ 8.1.1. Example ═══ struct { unsigned long int f; } *A[256]; #bitset A[]^.f; #end is translated to VAR A = ARRAY [0..255] OF POINTER TO RECORD f: BITSET END; ═══ 8.2. #merge ═══ #merge ( | "file_name" ) This directive lists included header files which should be merged even if the HeadersMerging option is OFF. This feature may be useful in some cases. The #merge directive has effect only in the file where it is located, or in the file specified in the surrounding #module directive,  Example ═══ 8.2.1. Example ═══ Have to write something here. ═══ 8.3. #module ═══ #module ( | "Pattern" ) Prologue #final Epilogue #end Pattern is a regular expression representing a set of file names. Prologue and Epilogue are arbitrary sequences of C language tokens. Prologue is inserted at the beginning of any header file which name matches Pattern; Epilogue is appended to its end. #final and Epilogue may be omitted. This directive is intended to be used in the project file. In this case, Prologue usually contains other non-standard preprocessor directives, like #merge, #bitset, and #parameters, which set translation rules for header files matching Pattern. The #module directives may not be nested. ═══ 8.4. #name ═══ #name ( | "file_name" ) identifier H2D replaces file_name with identifier everywhere. This might be useful when file_name contains special characters (e.g. my-header.h), or when there are headers with equal names in different directories (e.g. errno.h and sys\errno.h). ═══ 8.5. #parameters ═══ #parameters Parameter ":" Modifier ";" #end Parameter = identifier "(" number ")" Modifier = "VAR" | "ARRAY" | "VAR ARRAY" Parameter specifies an identifier of a function and a zero-based number of its parameter. Modifier specifies a translation rule for that parameter: ─────────────────────────────────── Modifier T *p is translated to VAR VAR p: T ARRAY p: ARRAY OF T VAR ARRAY VAR p: ARRAY OF T ─────────────────────────────────── By default, pointer-type parameter is translated to pointer-type parameter. H2D automatically declares the required formal type if there's no suitable type. The #parameters directive has effect only in the file where it is located, or in the file specified in the surrounding #module directive, so designators should specify parameters of functions declared in this file. If there is no function parameter specified by a designator or if it is not of the pointer type, an error message is displayed. See also Pointer type function parameters.  Example ═══ 8.5.1. Example ═══ #parameters function(0): VAR ARRAY; #end void function(char*); is translated to: PROCEDURE function ( VAR arg0: ARRAY OF CHAR ); ═══ 9. Options Reference ═══ This chapter contains brief descriptions of all options that may be specified in the configuration file.  Description of options ═══ 9.1. Description of options ═══ For each option, a set of possible values is given in parenthesis: ─────────────────────────────────────────────── string an arbitrary sequence of characters numeric an unsigned integer number boolean ON or OFF ─────────────────────────────────────────────── Options which control mapping of C base types to Modula-2 are described in C base types mapping.  BackEnd - specify target compiler back-end  CommentPosition - set preserved comments position  CPPComment - control C++ comments recognition  CStdLib - C standard library  DefinitionFilePrefix - definition module name prefix  GenerateMacroFile - enable macro module generation  HeadersMerging - merge all headers  HeadInserting - insert merged headers separators  LongFileName - enables directory prefixing  M2UnpackTypes -  MacrosFilePrefix - macro module name prefix  MaxStrLen - !!! line width in the generated text  OutputExtension - definition modules extension  PacketFile - packet file name  PreHeader - pre-header file name  Progress - enable progress indicator  Retranslate - ??? ═══ 9.1.1. BackEnd - specify target compiler back-end ═══ (Native/C_Code/Common) This option control generation of definition modules suitable for either Native XDS, XDS-C or both. It also affect generation of additional modules (See Fitting Modula-2 compiler). Default: Common - both Native XDS and XDS-C. ═══ 9.1.2. CommentPosition - set preserved comments position ═══ (numeric) Set starting position of comments preserved by H2D in output files. Has effect only on comments which are placed next to declarations. Default: delimit comment with a single blank. ═══ 9.1.3. CPPComment - control C++ comments recognition ═══ (boolean) If this option is set ON, H2D recognizes C++-style comments (started with '//') in header files. Default: OFF - do not recognize C++ comments. ═══ 9.1.4. CStdLib - C standard library ═══ (boolean) Sets value of the CSTDLIB XDS option in output definition modules corresponding to top-level header files (listed on the command line or in a project file. Default: OFF - set CSTDLIB off in definition modules. ═══ 9.1.5. DefinitionFilePrefix - definition module name prefix ═══ (string) Sets a prefix which has to be added to names of generated definition modules. Required only if these modules are intended to be used with XDS-C (the BackEnd option it set to C_Code or Common). In this case additional header files (wrappers) are generated, which names must differ from the original C header files to avoid conflicts (See Convertor to C). Default: no prefix (this should be true only for Native) !!! ═══ 9.1.6. GenerateMacroFile - enable macro module generation ═══ (boolean) Setting this option ON forces H2D to produce template modules for function-like C macros encountered in header files. Template means that implementation modules contain procedures with empty bodies; the actual code has to be written by hand. These modules has not to be imported, but to be added to the link list. See also Native code. This option is ignored if the target is XDS-C (the BackEnd option is set to C_Code). Default: OFF - do not generate macro modules. ═══ 9.1.7. HeadersMerging - merge all headers ═══ (boolean) If this option is set ON, H2D merges all header files included into the translated header by means of the #include directive. If this option is set OFF, H2D generates separate definition module for each header which is not specified in the #merge directive. See also Headers inclusion and Included headers. Default: OFF - do not merge headers which are not specified in the #merge directive. ═══ 9.1.8. HeadInserting - insert merged headers separators ═══ (boolean) Setting this option ON forces H2D to insert a comment containing name of a merged header before declarations from that header. Default: OFF - do not insert separators ═══ 9.1.9. LongFileName - enables directory prefixing ═══ (boolean) This option controls translation of the #include directive in cases when a specified file name contains directories. If this option is set OFF, H2D strips directory names. Otherwise directory names are kept and separators are replaced with underscore characters: #include IMPORT sys_errno; Default: OFF - strip directory names ═══ 9.1.10. M2UnpackTypes - ═══ (boolean) Sets value of the M2UNPACKTYPES XDS option in output definition modules. See C base types mapping for more information. Default: OFF - set M2UNPACKTYPES off in definition modules. ═══ 9.1.11. MacrosFilePrefix - macro module name prefix ═══ (string) Sets a prefix which has to be added to the names of template macro modules (See Native code). Should be empty when H2D is used with XDS-C. Default: _ (underscore) ═══ 9.1.12. MaxStrLen - !!! line width in the generated text ═══ (numeric) Sets maximum length of a string in the output file. Default: do not limit string length. ═══ 9.1.13. OutputExtension - definition modules extension ═══ (string) Sets the extension of output files (containing definition modules), without extension separator. The funny thing is that there is no similar option for implementation modules which always have "mod" extension. This is subject to change. Default: def. ═══ 9.1.14. PacketFile - packet file name ═══ (string) Sets the name of a file containing a list of input header files (one file name on a line). File names are read from this file is H2D is invoked with no arguments (See Packet file). Default: no packet file. ═══ 9.1.15. PreHeader - pre-header file name ═══ (string) Sets the name of a pre-header file, which is implicitly included at the beginning of each translated header (See ???). Default: no pre-header file. ═══ 9.1.16. Progress - enable progress indicator ═══ (boolean) Setting this option ON enables progress indicator. Default: OFF - show no progress indicator ═══ 9.1.17. Retranslate - ??? ═══ (boolean) If this option is set OFF, H2D does not translate a header file if a definition module corresponding to it already exists. Otherwise, H2D produces a new definition module which may overwrite the old one. See also Redirection file. Default: OFF - do not process already translated headers ═══ 10. xTech Development System ═══ xTech Development System (XDS) is a professional system featuring Modula-2 and Oberon-2 programming languages. It is available for most popular platforms, including OS/2, Linux, Windows NT, Windows 95, DOS, Unix workstations (Sun, HP, DEC, MIPS), etc. XDS provides an uniform programming environment for all mentioned platforms and allows to design and implement truly portable software. The XDS Modula-2 compiler implements ISO standard of Modula-2. The ISO standard library set is accessible for both Modula-2 and Oberon-2. All XDS implementations share the same platform-independent front-end for both source languages. The output code can be either native code for the target platform (Native XDS) or text in the ANSI C language (XDS-C). The ANSI C code generation is available for all platforms. A number of platforms for which a native code compiler is available is constantly extended. XDS includes standard ISO and PIM libraries along with a set of utility libraries and an interface to the ANSI C library set. Native XDS-x86 produces highly optimized 32-bit code for Intel x86 family. It is available for OS/2, Linux, Win32 (NT/95), and PC/MS-DOS. XDS for OS/2 and Win32 platforms come with two major enhancements: the IDE and the interface to the host operating system API for both Modula-2 and Oberon-2. For more information about XDS, please visit our Web page at: http://www.iis.nsk.su/xtech/xds/ Our e-mail address is: xds@iis.nsk.su